package tests;

import static org.junit.Assert.assertEquals;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.Set;

import org.joda.time.LocalDate;
import org.junit.Before;
import org.junit.Test;

import ui.CreateEditTaskDialog.TaskData;
import entity.general.MinTime;
import entity.main.DeadlineBeforeStartDateException;
import entity.main.DuplicateTaskNameException;
import entity.main.Objective;
import entity.main.ObjectiveTaskManager;
import entity.main.Task;
import entity.main.Task.TaskType;

public class ObjectiveTaskManagerTests {

	@Before
	public void setUp() throws Exception {
	}

	@Test
	public void testHasDefaultObjective() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		Set <Objective> objectives = otm.getObjectives();
		assertEquals(1, objectives.size());
		Objective objective = objectives.iterator().next();
		assertEquals(new Objective("Other"), objective);
	}

	@Test
	public void testAddObjective() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		otm.addObjective("Second");
		otm.addObjective("Second");
		Set <Objective> objectives = otm.getObjectives();
		assertEquals(2, objectives.size());

		Set <Objective> desired = new HashSet<>();
		desired.add(new Objective("Other"));
		desired.add(new Objective("Second"));
		
		assertEquals(desired, objectives);
	}

//	private String name;
//	private Time timePlanned;
//
//	private Time timeTakenToday = new Time(0,0);
//	private LocalDate today;
//	
//	private List <Pair <LocalDate, Time>> timeSpentOnTask = new ArrayList<>();
//	
//	private String description;
//	private Objective parentObjective;
//	private LocalDate deadline;
//
//	private LocalDate startDate;
	@Test
	public void testAddTask() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		otm.addObjective("Second");

		otm.addTaskWithoutDeadline("Name1", TaskType.GOAL, LocalDate.now(), "Description", new MinTime(3, 30));
		otm.addTaskWithoutDeadline("Name2", TaskType.GOAL, "Other", LocalDate.now(), "Description", new MinTime(3, 30));
		otm.addTaskWithoutDeadline("Name3", TaskType.GOAL, "Second", LocalDate.now(), "Description", new MinTime(3, 30));

		otm.addTaskWithDeadline("Name4", TaskType.GOAL, LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30));
		otm.addTaskWithDeadline("Name5", TaskType.GOAL, "Second", LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30));
		
		//public Task(String name, LocalDate startDate, LocalDate deadline, String description, Time timePlanned) {
		Set <Task> desiredTasks = new HashSet<>();
		desiredTasks.add(new Task("Name1", TaskType.GOAL, new Objective("Other"), LocalDate.now(), "Description", new MinTime(3, 30)));
		desiredTasks.add(new Task("Name2", TaskType.GOAL, new Objective("Other"), LocalDate.now(), "Description", new MinTime(3, 30)));
		desiredTasks.add(new Task("Name3", TaskType.GOAL, new Objective("Second"), LocalDate.now(), "Description", new MinTime(3, 30)));
		desiredTasks.add(new Task("Name4", TaskType.GOAL, new Objective("Other"), LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30)));
		desiredTasks.add(new Task("Name5", TaskType.GOAL, new Objective("Second"), LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30)));
		
		assertEquals(desiredTasks, otm.getTasks());
	}

	@Test
	public void testEditTask() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		otm.addObjective("Second");

		otm.addTaskWithoutDeadline("Name1", TaskType.GOAL, LocalDate.now(), "Description", new MinTime(3, 30));
		Task task = otm.getTaskByName("Name1");
		
//		public TaskData(String n, String d, MinTime at, TaskType tt, String cat)		
//		public TaskData(String n, String d, MinTime at, TaskType tt, String cat, LocalDate dead)

		TaskData taskData = new TaskData("Name2", task.getDescription(), task.getTimePlanned(), task.getType(), task.getParentObjective().getName());
		otm.editTask(task, taskData);
		
		Set <Task> desiredTasks = new HashSet<>();
		desiredTasks.add(new Task("Name2", TaskType.GOAL, new Objective("Other"), LocalDate.now(), "Description", new MinTime(3, 30)));
		
		assertEquals(desiredTasks, otm.getTasks());
	}

	
	@Test (expected = DeadlineBeforeStartDateException.class)  
	public void testDeadlineBeforeTodayTask() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		
		otm.addTaskWithDeadline("Name1", TaskType.GOAL, LocalDate.now(), new LocalDate(1980, 10, 10), "Description", new MinTime(3, 30));
	}

	@Test (expected = DuplicateTaskNameException.class)  
	public void testAddTaskWithSameNameTwice() {
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		
		otm.addTaskWithoutDeadline("Name1", TaskType.GOAL, LocalDate.now(), "Description", new MinTime(3, 30));
		otm.addTaskWithoutDeadline("Name1", TaskType.GOAL, LocalDate.now(), "Description", new MinTime(3, 30));
	}

	@Test
	public void testSerializeTaskManager() throws Exception
	{
		ObjectiveTaskManager otm = new ObjectiveTaskManager();
		otm.addObjective("Second");

		otm.addTaskWithoutDeadline("Name1", TaskType.GOAL, LocalDate.now(), "Description", new MinTime(3, 30));
		otm.addTaskWithoutDeadline("Name2", TaskType.GOAL, "Other", LocalDate.now(), "Description", new MinTime(3, 30));
		otm.addTaskWithoutDeadline("Name3", TaskType.GOAL, "Second", LocalDate.now(), "Description", new MinTime(3, 30));

		otm.addTaskWithDeadline("Name4", TaskType.GOAL, LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30));
		otm.addTaskWithDeadline("Name5", TaskType.GOAL, "Second", LocalDate.now(), new LocalDate(2020, 10, 10), "Description", new MinTime(3, 30));
		
		OutputStream outfile = new FileOutputStream("ObjTaskManagerTest.ser");
		OutputStream outbuffer = new BufferedOutputStream(outfile);
		ObjectOutput output = new ObjectOutputStream(outbuffer);
		output.writeObject(otm);
		output.close();
		
		InputStream infile = new FileInputStream("ObjTaskManagerTest.ser");
		InputStream buffer = new BufferedInputStream(infile);
		ObjectInput input = new ObjectInputStream(buffer);

		ObjectiveTaskManager otm2 = (ObjectiveTaskManager) input.readObject();
		input.close();
		assertEquals(otm.getTasks(), otm2.getTasks());
	}

}
